package com.yc.services;

import com.aliyun.oss.OSS;
import com.yc.config.OSSConfig;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class OSSService {
    // 创建日志记录器
    private static final Logger logger = LoggerFactory.getLogger(OSSService.class);


    @Autowired
    private OSSConfig ossConfig;
    @Autowired
    private OSS ossClient;
    @Autowired
    private StringRedisTemplate redisTemplate;

    // Redis键前缀
    private static final String IMAGE_FINGERPRINT_PREFIX = "image:md5:";
    // 指纹缓存时间（天）
    private static final long FINGERPRINT_EXPIRE_DAYS = 30;


    /**
     * 上传多个文件,返回总url，用逗号进行分割的
     * @param files
     * @return
     */
    public List<String> uploadFiles(MultipartFile[] files) {
        // 验证总大小
        long totalSize = Arrays.stream(files)
                .mapToLong(MultipartFile::getSize)
                .sum();
        logger.info("文件总大小为:{}",totalSize);
        if (totalSize > ossConfig.getMaxTotalSize()) {
            throw new RuntimeException("上传失败：总文件大小不能超过50MB");
        }

        List<String> urls = new ArrayList<>();

        // 验证每个文件
        for (MultipartFile file : files) {
            // 验证单个文件大小
            logger.info("文件{}大小为:{}",file.getOriginalFilename(),file.getSize());
            if (file.getSize() > ossConfig.getMaxSingleFileSize()) {
                throw new RuntimeException(
                        String.format("文件[%s]超过10MB限制", file.getOriginalFilename())
                );
            }

            // 验证文件类型
            logger.info("文件{}类型为:{}",file.getOriginalFilename(),file.getContentType());
            if (!isAllowedFileType(file.getContentType())) {
                throw new RuntimeException(
                        String.format("文件[%s]类型不支持，仅允许图片/PDF/Word/Excel",
                                file.getOriginalFilename())
                );
            }
            // 新增：查重校验
            String fileUrl = checkDuplicateAndUpload(file);
            urls.add(fileUrl);
        }
        return urls;
    }

    /**
     * 上传图片到OSS并返回URL
     * @param file 图片文件
     * @return 图片访问URL
     */
    public String uploadImage(MultipartFile file) {
        // 验证文件类型
        if (!file.getContentType().startsWith("image/")) {
            throw new RuntimeException("仅支持图片文件");
        }

        // 验证文件大小
        if (file.getSize() > 5 * 1024 * 1024) { // 5MB限制
            throw new RuntimeException("图片大小不能超过5MB");
        }

        try {
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = "psychology-analysis/" + UUID.randomUUID() + fileExtension;

            // 上传文件
            ossClient.putObject(ossConfig.getBucketName(), fileName, file.getInputStream());

            // 返回访问URL
            return "https://" + ossConfig.getBucketName() + "."
                    + ossConfig.getEndpoint() + "/" + fileName;

        } catch (Exception e) {
            throw new RuntimeException("图片上传失败", e);
        }
    }

    /**
     * 上传二维码图片到OSS
     * @param inputStream 二维码图片流
     * @param fileName 文件名（不包含路径）
     * @return 图片访问URL
     */
    public String uploadQRCode(InputStream inputStream, String fileName) {
        try {
            String bucketName = ossConfig.getBucketName();
            String endpoint = ossConfig.getEndpoint();
            
            // 生成文件路径
            String filePath = "qr-codes/" + fileName;
            
            // 上传文件
            ossClient.putObject(bucketName, filePath, inputStream);
            
            // 返回访问URL
            String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
            
            logger.info("二维码上传成功，URL: {}", url);
            return url;
            
        } catch (Exception e) {
            logger.error("二维码上传失败", e);
            throw new RuntimeException("二维码上传失败: " + e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                logger.warn("关闭输入流失败", e);
            }
        }
    }

    private String checkDuplicateAndUpload(MultipartFile file) {
        try (InputStream inputStream = file.getInputStream()) {
            // 1. 计算文件MD5指纹
            String md5 = DigestUtils.md5Hex(inputStream);
            String redisKey = IMAGE_FINGERPRINT_PREFIX + md5;

            // 2. 查询Redis是否存在该指纹
            String existingUrl = redisTemplate.opsForValue().get(redisKey);
            if (existingUrl != null) {
                logger.info("文件{}已存在，URL为:{}",file.getOriginalFilename(),existingUrl);
                return existingUrl; // 直接返回已存在的URL
            }

            // 3. 无重复则上传OSS
            logger.info("文件{}不存在，开始上传",file.getOriginalFilename());
            String newUrl = uploadToOSS(file);

            // 4. 将指纹-URL存入Redis
            logger.info("文件{}上传成功，URL为:{}",file.getOriginalFilename(),newUrl);
            redisTemplate.opsForValue().set(
                    redisKey,
                    newUrl,
                    FINGERPRINT_EXPIRE_DAYS,
                    TimeUnit.DAYS
            );

            return newUrl;
        } catch (IOException e) {
            throw new RuntimeException("文件处理失败", e);
        }
    }

    private boolean isAllowedFileType(String mimeType) {
        return Arrays.asList(ossConfig.getAllowedMimeTypes())
                .contains(mimeType.toLowerCase());
    }

    // 在 OSSService 中修改 uploadToOSS 方法
    private String uploadToOSS(MultipartFile file) {
        String bucketName = ossConfig.getBucketName();
        String endpoint = ossConfig.getEndpoint();

        try {
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = "psychology-analysis/" + UUID.randomUUID() + fileExtension;

            // 上传文件
            ossClient.putObject(bucketName, fileName, file.getInputStream());

            // 生成标准的 HTTPS URL（确保包含协议头）
            return "https://" + bucketName + "." + endpoint + "/" + fileName;

        } catch (Exception e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

//    private String uploadToOSS(MultipartFile file) {
//        // 获取配置
//        String bucketName = ossConfig.getBucketName();
//        String endpoint = ossConfig.getEndpoint();
//
//        try {
//            // 获取文件原始名称
//            String originalFilename = file.getOriginalFilename();
//
//            // 生成新的文件名（防止重复）
//            String fileName = "headpics/" + UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
//
//            // 上传文件流
//            ossClient.putObject(bucketName, fileName, file.getInputStream());
//
//            // 返回文件的访问地址
//            // 格式：https://bucket-name.endpoint/file-name
//            return "https://" + bucketName + "." + endpoint + "/" + fileName;
//        } catch (IOException e) {
//            throw new RuntimeException("文件上传失败", e);
//        }
//    }


}
